package com.bestvike.stone.core.util.area;

import com.bestvike.stone.core.lang.Environment;
import com.bestvike.stone.core.lang.StringUtils;
import lombok.extern.apachecommons.CommonsLog;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * Created by 许崇雷 on 2018-07-31.
 */
@CommonsLog
public final class AreaSpider {
    private static final String CHARSET = "GBK";
    private static final String HOME = "http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2017/index.html";
    private static final int CONN_TIMEOUT = 1000;
    private static final int READ_TIMOUT = 1000;

    public static ProvinceCollection getProvinceCollection() {
        ProvinceCollection provinces = new ProvinceCollection();
        Document html = getDocument(HOME);
        Elements provincetrs = html.select("tr[class=provincetr]");
        Elements provinceLinks = provincetrs.select("a[href]");
        for (Element provinceLink : provinceLinks) {
            String provinceHref = provinceLink.attr("href");
            if (provinceHref == null || provinceHref.length() != 7)
                throw new RuntimeException("provinceHref length not equals 7");
            String code = provinceHref.substring(0, 2);
            String name = provinceLink.text();
            String provinceUrl = getUrl(HOME, provinceHref);
            log.info(name);
            Collection<City> cityCollection = getCityCollection(provinceUrl);
            provinces.add(new Province(code, name, cityCollection));
        }
        return provinces;
    }

    private static Collection<City> getCityCollection(String provinceUrl) {
        List<City> cities = new ArrayList<>();
        Document html = getDocument(provinceUrl);
        Elements citytrs = html.select("tr[class=citytr]");
        for (Element citytr : citytrs) {
            Elements tds = citytr.select("td");
            Element codeElement = tds.first();
            String fullCode = codeElement.text();
            String code = fullCode.substring(0, 4);
            String name = tds.last().text();
            Element cityLink = codeElement.select("a").first();
            String cityHref = cityLink.attr("href");
            String cityUrl = getUrl(provinceUrl, cityHref);
            log.info("    " + name);
            Collection<County> countyCollection = getCountyCollection(code, cityUrl);
            cities.add(new City(code, name, countyCollection));
        }
        return cities;
    }

    private static Collection<County> getCountyCollection(String cityCode, String cityUrl) {
        List<County> counties = new ArrayList<>();
        Document html = getDocument(cityUrl);
        Elements countytrs = html.select("tr[class=countytr]");
        //广东省/东莞市 广东省/中山市 海南省/儋州市 没有区,直接有街道
        if (countytrs.isEmpty()) {
            Collection<Town> townCollection = getTownCollection(cityUrl);
            counties.add(new County(cityCode + "00", "市辖区", townCollection));
            return counties;
        }
        for (Element countytr : countytrs) {
            Elements tds = countytr.select("td");
            Element codeElement = tds.first();
            String fullCode = codeElement.text();
            String code = fullCode.substring(0, 6);
            String name = tds.last().text();
            Element countyLink = codeElement.select("a").first();
            if (countyLink == null) {
                counties.add(new County(code, name, null));
                continue;
            }
            String countyHref = countyLink.attr("href");
            String countyUrl = getUrl(cityUrl, countyHref);
            Collection<Town> townCollection = getTownCollection(countyUrl);
            counties.add(new County(code, name, townCollection));
        }
        return counties;
    }

    private static Collection<Town> getTownCollection(String countyUrl) {
        List<Town> towns = new ArrayList<>();
        Document html = getDocument(countyUrl);
        Elements towntrs = html.select("tr[class=towntr]");
        for (Element towntr : towntrs) {
            Elements tds = towntr.select("td");
            Element codeElement = tds.first();
            String fullCode = codeElement.text();
            String code = fullCode.substring(0, 9);
            String name = tds.last().text();
            towns.add(new Town(code, name));
        }
        return towns;
    }

    private static String getUrl(String baseUrl, String href) {
        return StringUtils.substringBeforeLast(baseUrl, Environment.Slash) + Environment.Slash + href;
    }

    private static Document getDocument(String url) {
        Document doc = null;
        do {
            try {
                URL uri = new URL(url);
                HttpURLConnection connection = (HttpURLConnection) uri.openConnection();
                connection.setConnectTimeout(CONN_TIMEOUT);
                connection.setReadTimeout(READ_TIMOUT);
                try (InputStream inputStream = connection.getInputStream()) {
                    doc = Jsoup.parse(inputStream, CHARSET, url);
                }
            } catch (Exception ignored) {
            }
        } while (doc == null);
        return doc;
    }
}
